/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.webos.java.base;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONObject;
import org.webos.java.base.workspace.FrameHolder;
import org.webos.java.base.workspace.Workspace;
import org.webos.java.root.Log;
import org.webos.java.root.RandomGUID;

/**
 *
 * @author Kostya
 */
abstract public class Frame<E extends Application> {
    private String instanceID = null;
    private String code = null;
    private String title = null;
    private Workspace parentWorkspace = null;
    private E application = null;
    private boolean closable = false;
    private boolean dynamic = false;
    private FrameHolder frameHolder = null;
    private boolean showStatus = false;
    String statusLine = " ";
    private String icon = "";
    private JSONObject data = new JSONObject();
    private Map<String, MessageHandler> handlers = new HashMap<String, MessageHandler>();

    public Frame(E aApplication, Workspace aWorkspace) {
        parentWorkspace = aWorkspace;
        application = aApplication;
        instanceID = new RandomGUID().toString();
        FrameType ft = getClass().getAnnotation(FrameType.class);
        if(ft!=null){
            code = application.getCode()+"-"+ft.code();
        }
    }

    public void setIcon(String icon) {
        this.icon = icon;
        application.frameTitleChanged(this);
    }

    public String getIcon() {
        return icon;
    }

    public Workspace getParentWorkspace() {
        return parentWorkspace;
    }
    
    public String getInstanceID() {
        return instanceID;
    }

    public String getCode() {
        return code;
    }

    public void setTitle(String title) {
        this.title = title;
        application.frameTitleChanged(this);
    }

    public String getTitle() {
        return title;
    }

    public E getApplication() {
        return application;
    }
    
    public void sendMessage(String aMethodName, JSONObject aMessage){
        try {
            JSONObject message = new JSONObject();
            message.put("type", "message");
            message.put("frame", instanceID);
            message.put("app", application.getCode());
            message.put("method", aMethodName);
            message.put("object", aMessage);
            application.getSession().sendMessage(message);
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
    }

    public void setWorkspace(Workspace aWorkspace){
        parentWorkspace = aWorkspace;
    }

    /**
     * @return the closable
     */
    public boolean isCloseable() {
        return closable;
    }

    /**
     * @param closable the closable to set
     */
    public void setCloseable(boolean closable) {
        this.closable = closable;
    }

    /**
     * @return the dynamic
     */
    public boolean isDynamic() {
        return dynamic;
    }

    /**
     * @param dynamic the dynamic to set
     */
    public void setDynamic(boolean dynamic) {
        this.dynamic = dynamic;
    }

    protected void close(){
        application.removeFrame(this);
    }

    /**
     * @return the frameHolder
     */
    public FrameHolder getFrameHolder() {
        return frameHolder;
    }

    /**
     * @param frameHolder the frameHolder to set
     */
    public void setFrameHolder(FrameHolder frameHolder) {
        this.frameHolder = frameHolder;
    }

    @RemoteMessage
    public void requestClose(JSONObject data){
        close();
    }

    public void setCode(String code) {
        this.code = code;
    }

    /**
     * @return the showStatus
     */
    public boolean isShowStatus() {
        return showStatus;
    }

    /**
     * @param showStatus the showStatus to set
     */
    public void setShowStatus(boolean showStatus) {
        this.showStatus = showStatus;
    }

    public void setStatus(String aStatus){
        try {
            statusLine = aStatus;
            JSONObject data = new JSONObject();
            data.put("status", aStatus);
            sendMessage("updateStatus", data);
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
    }

    public void terminate(){
        
    }

    /**
     * @return the data
     */
    public JSONObject getData() {
        return data;    
    }

    /**
     * @param data the data to set
     */
    public void setData(JSONObject data) {
        this.data = data;
    }

    public void addHandler(String aName, Object aObject){
        addHandler(aName, aObject, aName);
    }

    public void addHandler(String aName, Object aObject, String aMethod){
        try {
            Method[] arr = aObject.getClass().getDeclaredMethods();
            for (Method method : arr) {
                if(method.getName().equals(aMethod)){
                    handlers.put(aName, new MessageHandler(aName, aObject, method));
                }
            }
        } catch (Throwable t) {
            Log.error(this, "Exception thrown: " + t.getMessage());
            t.printStackTrace();
        }
    }

    public MessageHandler getHandler(String aName){
        return handlers.get(aName);
    }

}
